package com.alibaba.cloud.sentinel.feign;

import cn.trigram.config.DefaultErrorDecoder;
import feign.FeignException;
import feign.codec.ErrorDecoder;
import java.lang.reflect.Method;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

/**
 * 统一处理feign调用失败的代码。
 * <p>
 * 另一种方式是实现 {@link ErrorDecoder} 将feign调用时的异常转成自定义异常，然后抛出去交给ControllerAdvice处理
 *
 * @see DefaultErrorDecoder
 */
@Slf4j
@AllArgsConstructor
public class DefaultFallback<T> implements MethodInterceptor {

  private final Class<T> targetType;

  private final String targetName;

  private final Throwable cause;


  @Override
  public Object intercept(
      Object o, Method method, Object[] objects, MethodProxy methodProxy
  ) throws Throwable {

    String causeMessage = cause.getMessage();
    log.error("DefaultFallback[{}:{}] service-id:{},error:{}", targetType.getName(),
              method.getName(), targetName, causeMessage
    );
    if (!(cause instanceof FeignException)) {
//      这里处理调用请求失败的异常
      return null;
    }
//这里处理业务的异常，并返回对应类型的返回值
    return null;
  }

  @Override
  public boolean equals(Object o) {

    if (this == o) {
      return true;
    }
    if (!(o instanceof DefaultFallback)) {
      return false;
    }

    DefaultFallback<?> that = (DefaultFallback<?>)o;

    return targetType.equals(that.targetType);
  }

  @Override
  public int hashCode() {

    return targetType.hashCode();
  }

}
